/**
@author		Jong Min, Lee
@date		  10/01/2014
@breif		study class 

copyright(c) Tae Young Soft. All right reserved. 2014
*/
#include "stdafx.h"
#include "Taurus_DcmData/Study.h"
#include "Taurus_Util/Errors.h"
#include "Taurus_DcmData/DcmStudy.h"
#include "Taurus_DcmData/StudySet.h"
#include "Taurus_DcmData/Series.h"

CStudy::CStudy()
{
  init();
}

CStudy::~CStudy()
{
  destroy();
}

const TCHAR* CStudy::getKey() const
{
  return m_theDcmStudy->getKey();
}

void CStudy::init()
{
  m_theDcmStudy = NULL;
  m_theParent = NULL;
}

void CStudy::destroy() 
{
  m_theDcmStudy->decreaseRefCount();
  removeAllSeries();
}

DWORD CStudy::addSeries(CSeries* series)
{
  if(series == NULL) return ERROR_NOT_ENOUGH_MEMORY;

  try
  {
    if(series->isNoneImage())
      m_theNoneImageSeries.push_back(series);
    else
      m_theImageSeries.push_back(series);
  }
  catch(...)
  {
    return ERROR_NOT_ENOUGH_MEMORY;
  }

  series->setParent(this);
  return ERROR_SUCCESS;
}

void CStudy::removeAllSeries()
{
  removeAllImageSeries();
  removeAllNoneImageSeries();
}

void CStudy::removeAllImageSeries()
{
  clearSeriesArray(m_theImageSeries);
}

void CStudy::removeAllNoneImageSeries()
{
  clearSeriesArray(m_theNoneImageSeries);
}

void CStudy::clearSeriesArray(std::vector<CSeries*>& series)
{
  unsigned int numSeries = series.size();
  for(unsigned int i = 0; i < numSeries; ++i)
    _DELETE(series[i]);
  series.clear();
}

DWORD CStudyProducer::produce(CDcmStudy* dcmStudy, CStudySet* parent, CStudy* outStudy)
{
  if(dcmStudy == NULL) return ERROR_INVALID_PARAMETER;

  CStudy* newStudy = NULL;
  _TRY_ALLOC(newStudy, CStudy);
  if(newStudy == NULL) return ERROR_NOT_ENOUGH_MEMORY;

  DWORD error = attachDcmStudy(newStudy, dcmStudy, parent);
  if(error != ERROR_SUCCESS)
  {
    _DELETE(newStudy)
    return error;
  }

  unsigned int nNumImageSeries = dcmStudy->getNumImageSeries();
  try
  {
    newStudy->m_theImageSeries.reserve(nNumImageSeries);
  }
  catch(...)
  {
    _DELETE(newStudy);
    return ERROR_NOT_ENOUGH_MEMORY;
  }

  for(unsigned i = 0; i < nNumImageSeries;++i)
  {
    CDcmSeries* dcmSeries = dcmStudy->getImageSeries(i);
    if(dcmSeries == NULL) continue;

    CSeries* newSeries = NULL;
    error = CSeriesProducer::produce(dcmSeries, newStudy, newSeries);
    if(error != ERROR_SUCCESS)
    {
      _DELETE(newStudy)
      return error;
    }

    newStudy->m_theImageSeries.push_back(newSeries);
  }

  if(newStudy->m_theImageSeries.size() == 0)
  {
    _DELETE(newStudy);
    return ERROR_INVALID_PARAMETER;
  }

  unsigned int numNoneImageSeries = dcmStudy->getNumNoneImageSeries();
  try
  {
    newStudy->m_theNoneImageSeries.reserve(numNoneImageSeries);
  }
  catch(...)
  {
    _DELETE(newStudy);
    return ERROR_NOT_ENOUGH_MEMORY;
  }

  for(unsigned int  i = 0; i < numNoneImageSeries; ++i)
  {
    CDcmSeries* dcmSeries = dcmStudy->getNoneImageSeries(i);
    if(dcmSeries == NULL) continue;

    CSeries* newSeries = NULL;
    error = CSeriesProducer::produce(dcmSeries, newStudy, newSeries);
    if(error != ERROR_SUCCESS)
    {
      _DELETE(newStudy);
      return ERROR_NOT_ENOUGH_MEMORY;
    }

    newStudy->m_theNoneImageSeries.push_back(newSeries);
  }

  outStudy = newStudy;

  return ERROR_SUCCESS;
}

DWORD CStudyProducer::produce(CDcmStudy* dcmStudy, 
                              CSeries** series, 
                              const unsigned int numSeries, 
                              CStudySet* parent, 
                              CStudy*& outStudy)
{
  if(dcmStudy == NULL) return ERROR_INVALID_PARAMETER;

  if(series == NULL || numSeries == 0) return ERROR_INVALID_PARAMETER;

  CStudy* newStudy = NULL;
  _TRY_ALLOC(newStudy, CStudy)
  if(newStudy == NULL) return ERROR_NOT_ENOUGH_MEMORY;

  DWORD error = attachDcmStudy(newStudy, dcmStudy, parent);
  if(error != ERROR_SUCCESS)
  {
    _DELETE(newStudy)
    return error;
  }

  //check the number of image series and none image series
  unsigned int numImageSeries = 0;
  unsigned int numNoneImageSeries = 0;
  for(unsigned int i = 0; i < numSeries; ++i)
  {
    if(series[i] == NULL) continue;

    if(series[i]->isNoneImage())
      numNoneImageSeries++;
    else
      numImageSeries++;
  }

  if(numImageSeries == 0)
  {
    _DELETE(newStudy)
    return ERROR_INVALID_PARAMETER;
  }

  //reserve memory
  try
  {
    newStudy->m_theImageSeries.reserve(numImageSeries);
    newStudy->m_theNoneImageSeries.reserve(numNoneImageSeries);
  }
  catch(...)
  {
    _DELETE(newStudy);
    return ERROR_INVALID_PARAMETER;
  }

  //add image series
  for(unsigned int i = 0; i < numSeries; ++i)
  {
    if(series[i] = NULL) continue;

    if(series[i]->isNoneImage())
      newStudy->m_theNoneImageSeries.push_back(series[i]);
    else
      newStudy->m_theImageSeries.push_back(series[i]);
  }

  outStudy = newStudy;

  return ERROR_SUCCESS;
}

DWORD CStudyProducer::attachDcmStudy(CStudy* study, 
                                     CDcmStudy* dcmStudy, 
                                     CStudySet* parent)
{
  if(study == NULL || dcmStudy == NULL)
    return ERROR_INVALID_PARAMETER;

  study->m_theDcmStudy = dcmStudy;
  study->m_theDcmStudy->increaseRefCount();
  study->m_theParent = parent;

  return ERROR_SUCCESS;
}